---
sidebar_label: Event Trigger payload
sidebar_position: 2
description: Event Trigger payload in Hasura
keywords:
  - hasura
  - docs
  - event trigger
  - payload
---

import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';

# Event Trigger Payload

## Introduction

Whenever data-driven events invoke an Event Trigger, the payload of the event is delivered to the webhook endpoint you
provide. The payload contains information about the event that was triggered, including the new or updated data, and —
when used with PostgreSQL — the session variables of the user who triggered the event.

## HTTP request method

Event Triggers are invoked using an HTTP `POST` request with the following headers:

```text
Content-Type: application/json
```

## JSON payload

In the request object, the payload makes up the majority of the content. The payload is a JSON object with the following
structure:

```json
{
  // Headers above are not shown
  "payload": {
    "created_at": "<TIMESTAMP>",
    "delivery_info": {
      "current_retry": "<RETRY_NUMBER>",
      "max_retries": "<MAX_RETRIES>"
    },
    "event": {
      "data": {
        "new": "<OBJECT_OF_COLUMNS_AND_VALUES>",
        "old": "<OBJECT_OF_COLUMNS_AND_VALUES|NULL>"
      },
      "op": "<INSERT|UPDATE|DELETE|MANUAL>",
      "session_variables": {
        "x-hasura-role": "<ROLE_NAME>"
      },
      "trace_context": {
        "span_id": "<SPAN_ID>",
        "trace_id": "<TRACE_ID>"
      }
    },
    "id": "<UUID_FOR_INVOCATION>",
    "table": {
      "name": "<TABLE_NAME>",
      "schema": "<SCHEMA_NAME>"
    },
    "trigger": {
      "name": "<TRIGGER_NAME>"
    }
  }
  // Version below is not shown
}
```

| Key                                     | Type             | Description                                                                                                                                                 |
| --------------------------------------- | ---------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `created_at`                            | String           | Represents a timestamp value for the invocation of the trigger.                                                                                             |
| `delivery_info`                         | Object           | Contains information about message delivery retries.                                                                                                        |
| `delivery_info.current_retry`           | Integer          | Represents the current retry number.                                                                                                                        |
| `delivery_info.max_retries`             | Integer          | Represents the maximum number of retries.                                                                                                                   |
| `event`                                 | Object           | Represents an event and related data.                                                                                                                       |
| `event.data`                            | Object           | Contains data related to the event.                                                                                                                         |
| `event.data.new`                        | Object           | Object representing the new data associated with the event, with each key-value pair representing a column name and its value.                              |
| `event.data.old`                        | Object or `null` | Represents old data associated with the event or `null` if not applicable.                                                                                  |
| `event.op`                              | String           | Represents the name of the operation. Can only be "INSERT", "UPDATE", "DELETE", "MANUAL"                                                                    |
| `event.session_variables`               | Object           | Key-value pairs of session variables (i.e. "x-hasura-\*" variables) and their values (NULL if no session variables found) (**Only available for Postgres**) |
| `event.session_variables.x-hasura-role` | String           | Represents the role name of the user who triggered the event.                                                                                               |
| `event.trace_context`                   | Object           | Contains trace context information.                                                                                                                         |
| `event.trace_context.span_id`           | String           | Represents the span ID for tracing.                                                                                                                         |
| `event.trace_context.trace_id`          | String           | Represents the trace ID for tracing.                                                                                                                        |
| `id`                                    | String           | Represents a UUID for invocation.                                                                                                                           |
| `table`                                 | Object           | Represents information about the table.                                                                                                                     |
| `table.name`                            | String           | Represents the name of the table.                                                                                                                           |
| `table.schema`                          | String           | Represents the schema name of the table.                                                                                                                    |
| `trigger`                               | Object           | Represents information about the trigger.                                                                                                                   |
| `trigger.name`                          | String           | Represents the name of the trigger.                                                                                                                         |

<Tabs groupId="user-preference" className="json-payloads">
<TabItem value="postgres" label="Postgres">

Below, you'll find examples of the `new` and `old` objects for each operation type.

- INSERT
  - `event.data.old` will be `null`
  - `event.data.new` will contain the insert row
- UPDATE
  - `event.data.old` will be values before the update
  - `event.data.new` will contain the values after the update
- DELETE
  - `event.data.old` will contain the row that is deleted
  - `event.data.new` will be `null`
- MANUAL
  - `event.data.old` will be `null`
  - `event.data.new` will contain the current row

:::info Note

- In case of `UPDATE`, the events are delivered only if new data is distinct from old data. The
  [composite type comparison](https://www.postgresql.org/docs/current/functions-comparisons.html#COMPOSITE-TYPE-COMPARISON)
  is used to compare the old and new rows. If rows contain columns, which cannot be compared using `<>` operator, then
  internal binary representation of rows by Postgres is compared.
- [Table computed fields](/schema/postgres/computed-fields.mdx) are not included in the Event Trigger payload data

:::

</TabItem>
<TabItem value="mssql" label="MSSQL">

Below, you'll find examples of the `new` and `old` objects for each operation type.

- INSERT
  - `event.data.old` will be `null`
  - `event.data.new` will contain the insert row
- UPDATE
  - If a row is updated and the primary key is also updated
    - `event.data.old` will be `null`
    - `event.data.new` will contain the values after the update
  - If a row is updated and the primary key is unchanged
    - `event.data.old` will be values before the update
    - `event.data.new` will contain the values after the update
- DELETE
  - `event.data.old` will contain the row that is deleted
  - `event.data.new` will be `null`
- MANUAL
  - `event.data.old` will be `null`
  - `event.data.new` will contain the current row

:::info Note

- In case of `UPDATE`, the events are delivered only if new data is distinct from old data. We use the primary keys to
  join the temporary tables `inserted` and `deleted` tables to correlate the old and new data.
- `UPDATE` event triggers will only work on tables which have primary keys.
- Since we use the primary key to co-relate DELETED and INSERTED table, if the primary key is updated then it is not
  possible to correlate the `old` and `new` data. Hence, only `new` data is sent in this case.

:::

</TabItem>
</Tabs>

### Example

Below, we have an example of the payload for an `INSERT` operation.

```json
{
  "payload": {
    "created_at": "2020-07-29T10:00:00.000Z",
    "delivery_info": {
      "current_retry": 0,
      "max_retries": 0
    },
    "event": {
      "data": {
        "new": {
          "id": 1,
          "name": "John"
        },
        "old": null
      },
      "op": "INSERT",
      "session_variables": {
        "x-hasura-role": "admin"
      },
      "trace_context": {
        "span_id": "123",
        "trace_id": "456"
      }
    },
    "id": "123e4567-e89b-12d3-a456-426614174000",
    "table": {
      "name": "users",
      "schema": "public"
    },
    "trigger": {
      "name": "insert_user"
    }
  }
}
```

:::info Parsing the payload

You can access data from the request by parsing the JSON payload. For example, to access the new user's id, you can use
`req.body.event.data.new.id` to get the value `1`.

:::

## Webhook response structure

A `2xx` response status code is deemed to be a successful invocation of the webhook. Any other response status will be
deemed as an unsuccessful invocation which will cause retries as per the retry configuration.

After executing your business logic in the webhook, it's recommended that you return a JSON object in your webhook's
response.

### Retry-After header

If the webhook response contains a `Retry-After` header, then the event will be redelivered once more after the duration
(in seconds) found in the header. Note that the header will be respected only if the response status code is `non-2xx`.

The `Retry-After` header can be used for retrying/rate-limiting/debouncing your webhook triggers.
